From e862b83e8433d8b898b09079dacbffb3bd42af9f Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Wed, 10 Sep 2008 11:09:08 +0100 Subject: [PATCH] CPUIDLE: Avoid remnant HPET intr while force hpetbroadcast Exit from C3 is mainly caused by HPET intr if force enable hpetbroadcast. But it is still probably caused by other unexpected events. In this case the HPET timer may still be alive while there is no CPU in C3. Avoid those remnant HPET intr can save cpu handling time and increase idle time. Signed-off-by: Wei Gang --- xen/arch/x86/hpet.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/hpet.c b/xen/arch/x86/hpet.c index 147705d2f0..31028cc2a6 100644 --- a/xen/arch/x86/hpet.c +++ b/xen/arch/x86/hpet.c @@ -100,6 +100,13 @@ static int reprogram_hpet_evt_channel( ch->next_event = expire; + if ( expire == STIME_MAX ) + { + /* We assume it will take a long time for the timer to wrap. */ + hpet_write32(0, HPET_T0_CMP); + return 0; + } + delta = min_t(int64_t, delta, MAX_DELTA_NS); delta = max_t(int64_t, delta, MIN_DELTA_NS); delta = ns2ticks(delta, ch->shift, ch->mult); @@ -206,10 +213,10 @@ void hpet_broadcast_enter(void) { struct hpet_event_channel *ch = &hpet_event; - cpu_set(smp_processor_id(), ch->cpumask); - spin_lock(&ch->lock); + cpu_set(smp_processor_id(), ch->cpumask); + /* reprogram if current cpu expire time is nearer */ if ( this_cpu(timer_deadline) < ch->next_event ) reprogram_hpet_evt_channel(ch, this_cpu(timer_deadline), NOW(), 1); @@ -222,8 +229,17 @@ void hpet_broadcast_exit(void) struct hpet_event_channel *ch = &hpet_event; int cpu = smp_processor_id(); + spin_lock_irq(&ch->lock); + if ( cpu_test_and_clear(cpu, ch->cpumask) ) + { reprogram_timer(per_cpu(timer_deadline, cpu)); + + if ( cpus_empty(ch->cpumask) && ch->next_event != STIME_MAX ) + reprogram_hpet_evt_channel(ch, STIME_MAX, 0, 0); + } + + spin_unlock_irq(&ch->lock); } int hpet_broadcast_is_available(void) -- 2.30.2